#include "motorcalibdialog.h"
#include "ui_motorcalibdialog.h"
#include "userlogger.h"
#include "loading.h"
#include "logger.h"
#include "shadow.h"
#include <QTimer>

#define TIMER_INTERVAL 20
#define CALIB_TIMEOUT_COUNT 1500

enum CalibForm { Prepare, Calib, Finished };

MotorCalibDialog::MotorCalibDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::MotorCalibDialog)
{
    ui->setupUi(this);
    m_timer = new QTimer(this);
    connect(m_timer, &QTimer::timeout, this, [this] {
        if (m_counter++ > CALIB_TIMEOUT_COUNT) {
            sysDebug("motor calibrate timout");
            finished(false);
        }

        rotateImage();
    });

    initWidget();
}

MotorCalibDialog::~MotorCalibDialog()
{
    delete ui;
}

void MotorCalibDialog::show(bool forceCalib)
{// 进入界面，先让电机失能
    BllController::getInstance()->setInstrumentStauts(Status::MotorCalib);
    m_forceCalib = forceCalib;
    changePage(Prepare);
    releaseMotor();
    exec();
}

void MotorCalibDialog::on_btnOK_clicked()
{
    if (m_success)
    {// 校准成功，重启机器
        close();
        Loading::showLoading(QColor(0,0,0,200), false, tr("Shutting down"));
        ComCmd cmd = { PWROFF, 0, 0, 0, 0, 0 };
        BllController::getInstance()->sendPortCmd(cmd);
    }
    else if (m_forceCalib)
    {// 强制校准，校准失败，再次重试
        releaseMotor();
        changePage(Prepare);
    }
    else
    {// 非强制校准，校准失败，直接关闭
        close();
    }
}

void MotorCalibDialog::on_btnClose_clicked()
{
    close();
}

void MotorCalibDialog::on_btnCalib_clicked()
{
    sysDebug("start motor calibrate...");
    UserLogger::log(tr("Start Motor Calibrate"));
    connect(BllController::getInstance(), &BllController::motorCalibDoneSignal, this, &MotorCalibDialog::onMotorCalibDone);
    m_counter = 0;
    m_angle = 0;
    m_timer->start(TIMER_INTERVAL);
    changePage(Calib);

    ComCmd cmd = { XZDJSZ, 0, 0, 0, 0, 0 };
    BllController::getInstance()->sendPortCmd(cmd);
}

void MotorCalibDialog::onMotorCalibDone(const HostReply &host)
{
    bool success = (host.parameter.toInt() == 1);
    finished(success);
}

void MotorCalibDialog::releaseMotor()
{
    sysDebug("release motor...");
    ComCmd cmd = { XZDJSN, 0, 0, 0, 0, 0 };
    BllController::getInstance()->sendPortCmd(cmd);
}

void MotorCalibDialog::finished(bool success)
{
    sysDebug("motor calibrate: %s", success ? "Success" : "Fail");
    UserLogger::log(QString("%1 %2").arg(tr("Motor Calibrate")).arg(success ? "Success" : "Fail"));
    disconnect(BllController::getInstance(), &BllController::motorCalibDoneSignal, this, &MotorCalibDialog::onMotorCalibDone);
    m_timer->stop();
    m_success = success;
    changePage(Finished);
}

void MotorCalibDialog::setCloseButtonVisible(bool show)
{
    ui->btnClose->setVisible(show);
}

void MotorCalibDialog::changePage(int index)
{
    setCloseButtonVisible((Calib != index) && !m_forceCalib);

    if (Finished == index)
    {
        ui->lblFinishedText->setText(m_success ? tr("Calibration completed, please restart") : tr("Calibration failed, please try again"));
    }

    ui->stackedWidget->setCurrentIndex(index);
}

void MotorCalibDialog::initWidget()
{
    if (windowWidth >= 1280) {
        setProperty("cssSize", "large");
        setGeometry(0, 0, 1280, 800);
        ui->btnWidget->setMinimumHeight(80);
        ui->btnWidgetOK->setMinimumHeight(80);
    } else {
        setGeometry(0, 0, 1024, 600);
    }

    setParent(Project::Instance());
    setAttribute(Qt::WA_TranslucentBackground, true);
    QGraphicsDropShadowEffect *shadow = new QGraphicsDropShadowEffect();
    shadow->setColor(QColor(0, 0, 0, 150));
    shadow->setOffset(1, 1);
    shadow->setBlurRadius(16);
    ui->widget->setGraphicsEffect(shadow);
    m_pixmap.load(":/resources/loading.png");
}

void MotorCalibDialog::rotateImage()
{
    m_angle += 10;
    m_angle %= 360;
    QMatrix matrix;
    matrix.rotate(m_angle);
    QPixmap tmp(80, 80);
    tmp.fill(Qt::transparent);
    QPainter painter(&tmp);
    painter.setRenderHint(QPainter::SmoothPixmapTransform);
    painter.translate(40, 40);
    painter.rotate(m_angle);
    painter.translate(-40, -40);
    painter.drawPixmap(0, 0, 80, 80, m_pixmap);
    ui->icon->setPixmap(tmp);
}
